/*
 * File:   F13.h
 * Author: jcrada
 *
 * Created on 30 May 2011, 12:22 PM
 */

#ifndef ECB_CEC10_F13_H
#define	ECB_CEC10_F13_H

#include "ecb/benchmarks/cec10/CecProblem.h" 

#include "ecb/benchmarks/cec10/CecMath.h"
#include "ecb/operator/Permuted.h"
#include "ecb/operator/Grouped.h"
#include "ecb/operator/Shifted.h"
#include "ecb/function/Rosenbrock.h"
#include "ecb/function/Sphere.h"


namespace ecb{
    namespace cec10 {

        class F13 : public CecProblem {
        private:
            Function* sphere;
            std::vector<Function*> sumRosenbrock;
        public:

            F13(int dimensions, int mValue)
            : CecProblem("F13", "(D/2m)-group Shifted and m-rotated Rosenbrocks's Function", dimensions,
            -100, 100, true, mValue, new CecRandom(13l)) {

                std::vector<scalar> shift = CecMath::ShiftVector(dimensions, _properties->getMinimum(), _properties->getMaximum() - 1, randomizer());
                std::vector<int> permutation = CecMath::PermutationVector(dimensions, randomizer());
                std::vector<scalar> permutedShift(dimensions, 0);
                for (int i = 0; i < dimensions; ++i) {
                    permutedShift[i] = shift[permutation[i]];
                }
                for (int k = 0; k < dimensions / (2 * mValue); ++k) {
                    sumRosenbrock.push_back(
                            new Permuted(permutation, new Grouped(k * mValue, (k + 1) * mValue,
                            new Shifted(permutedShift, k * mValue, new Rosenbrock()))));
                }


                sphere = new Permuted(permutation, new Grouped(dimensions / 2, dimensions,
                        new Shifted(permutedShift, dimensions / 2, new Sphere())));

            }

            ~F13() {
                delete sphere;
                for (size_t i = 0; i < sumRosenbrock.size(); ++i) {
                    delete sumRosenbrock[i];
                }
            }

            scalar f(const std::vector<scalar>& x) {
                scalar result = 0;
                for (size_t i = 0; i < sumRosenbrock.size(); ++i) {
                    result += sumRosenbrock[i]->f(x);
                }
                return result + sphere->f(x);
            }
        };
    }
}

#endif	/* ECB_CEC10_F13_H */

